package fr.charlott.view;

import java.text.SimpleDateFormat;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.google.common.collect.Lists;

import fr.charlott.batch.JobListener;
import fr.charlott.tools.Constants;

@Controller("batchControler")
public class BatchControler {

    private Logger logger = LoggerFactory.getLogger(BatchControler.class);

    private Job importFiles;

    private SimpleJobLauncher simpleJobLauncher;

    private JobListener jobListener;

    private Integer progress;

    private static final int NB_STEPS = 5;

    @Autowired
    public BatchControler(SimpleJobLauncher simpleJobLauncher, Job importFiles, JobListener jobListener) {
        super();
        this.simpleJobLauncher = simpleJobLauncher;
        this.importFiles = importFiles;
        this.jobListener = jobListener;
    }

    public void start() throws Exception {
        progress = 0;
        JobParameters jobParameters = new JobParametersBuilder().addLong("timeStamp", Long.valueOf(System.currentTimeMillis())).toJobParameters();
        try {
            simpleJobLauncher.run(importFiles, jobParameters);
        } catch (JobExecutionAlreadyRunningException e) {
            e.printStackTrace();
        } catch (JobRestartException e) {
            e.printStackTrace();
        } catch (JobInstanceAlreadyCompleteException e) {
            e.printStackTrace();
        } catch (JobParametersInvalidException e) {
            e.printStackTrace();
        } catch (ItemStreamException e) {
            logger.error("le nom du fichier est incorrect", e);
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de fichier : ", "le nom du fichier est incorrect"));
        } catch (IllegalStateException e) {
            System.out.println("le nom du fichier est incorrect");
        } catch (Exception e) {
            System.out.println("une exception s'est produite !!");
        }
    }

    public Integer getProgress() {

        if (progress == null) {
            progress = 0;
        } else {
            progress = progress + (100 / NB_STEPS);
        }

        if (jobListener.getJobExecution() != null && jobListener.getJobExecution().isStopping()) {
            progress = 100;
        }

        if (progress > 100 || progress == 100) {
            progress = 100;
        }

        return progress;
    }

    public void onComplete() {
        Severity severity = FacesMessage.SEVERITY_INFO;

        long executionTime = jobListener.getJobExecution().getEndTime().getTime() - jobListener.getJobExecution().getStartTime().getTime();

        switch (jobListener.getJobExecution().getStatus()) {
        case COMPLETED:
            break;
        case FAILED:
            severity = FacesMessage.SEVERITY_ERROR;
            break;
        case ABANDONED:
            severity = FacesMessage.SEVERITY_WARN;
            break;
        default:
            break;
        }
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, "Statut : ", jobListener.getJobExecution().getStatus().name()));

        SimpleDateFormat dateStandard = new SimpleDateFormat(Constants.TIME_PATTERN);
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(severity, "Dernière mise à jour : ", dateStandard.format(jobListener.getJobExecution().getLastUpdated())));

        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, "Durée du job : ", String.valueOf(executionTime) + " ms"));

    }

    public void cancel() {

        if (jobListener.getJobExecution() != null && jobListener.getJobExecution().getStatus().equals(ExitStatus.EXECUTING)) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Statut : ", "Arret du job par l'utilisateur"));
            jobListener.getJobExecution().stop();
        }

        progress = null;
    }

    public List<StepExecution> getStepExecutions() {
        if (jobListener.getJobExecution() != null) {
            return Lists.newArrayList(jobListener.getJobExecution().getStepExecutions());
        }
        return Lists.newArrayList();
    }

}
